home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / util / boot / BPPCFixFix.lha / BPPCFixFix / src / bppcfixfix.e
Encoding:
Text File  |  2000-09-02  |  4.0 KB  |  150 lines

  1. -> FILE: ESrc:Own/bppcfixfix.e          REV: 1 --- patch p5/dce library to be loadable from disk
  2. /* History
  3.    0      Started in September 2000.
  4. */
  5.  
  6. OPT PREPROCESS
  7.  
  8. #define VERSION 'bppcfixfix 1.0.0 (1.9.2000)'
  9.  
  10. MODULE 'dos/dos','dos/doshunks','exec/memory','exec/execbase',
  11.        'graphics/gfxbase','exec/resident','exec/nodes'
  12.  
  13. ENUM ARG_FROM,ARG_TO,NUMARGS
  14.  
  15. ENUM ER_OK,ER_PARAM,ER_MEM,ER_INPUTFILE,ER_OUTPUTFILE,ER_READ,
  16.      ER_WRITE,ER_PATCH
  17.  
  18. DEF array[NUMARGS]:ARRAY OF LONG
  19.  
  20. PROC main() HANDLE
  21.   DEF rdargs = NIL, name:PTR TO CHAR, ioerr, ret
  22.   DEF r, pname[64]:STRING
  23.   DEF ifh = NIL, ofh = NIL, ofile
  24.   DEF filelen, buf
  25.  
  26.   IF (KickVersion(37) = 0)
  27.     WriteF('This program requires AmigaOS 2.04+\n');
  28.     RETURN RETURN_FAIL
  29.   ENDIF
  30.  
  31.   FOR r := 0 TO NUMARGS - 1; array[r] := 0; ENDFOR
  32.   IF ((rdargs := ReadArgs('FROM/A,TO/A',
  33.       array, NIL)) = NIL) THEN Raise(ER_PARAM)
  34.  
  35.   -> open input file
  36.   IF ((ifh := Open(array[ARG_FROM], MODE_OLDFILE)) = NIL) THEN Raise(ER_INPUTFILE)
  37.   -> open output file
  38.   ofile := array[ARG_TO]
  39.   IF ((ofh := Open(ofile, MODE_NEWFILE)) = NIL) THEN Raise(ER_OUTPUTFILE)
  40.  
  41.   buf := NewR(filelen := FileLength(array[ARG_FROM]))
  42.   IF (Read(ifh, buf, filelen) <> filelen) THEN Raise(ER_READ)
  43.   IF (patch(buf, filelen) = FALSE) THEN Raise(ER_PATCH)
  44.   IF (Write(ofh, buf, filelen) <> filelen) THEN Raise(ER_WRITE)
  45.  
  46. EXCEPT DO
  47.   IF (exception)
  48.     IF ((exception = "NEW") OR (exception = "MEM")) THEN exception := ER_MEM
  49.  
  50.     IF (ioerr := IoErr())
  51.       PrintFault(ioerr, NIL)
  52.     ENDIF
  53.     GetProgramName(pname, StrMax(pname) - 1)
  54.     PrintF('\s: \s\n', pname,
  55.            ListItem(['', 'argument error', 'no memory',
  56.                     'could not open input file',
  57.                     'could not open output file',
  58.                     'could not read file',
  59.                     'could not write file',
  60.                     'could not patch file'
  61.                     ], exception))
  62.     ret := RETURN_ERROR
  63.   ELSE
  64.     ret := RETURN_OK
  65.   ENDIF
  66.  
  67.   IF (ofh)
  68.     Close(ofh)
  69.     IF (exception) THEN DeleteFile(ofile)
  70.   ENDIF
  71.   IF (ifh) THEN Close(ifh)
  72.   IF (rdargs) THEN FreeArgs(rdargs)
  73. ENDPROC ret
  74.  
  75. CHAR '$VER: ',VERSION,0
  76.  
  77.  
  78. PROC patch(buf:PTR TO LONG, len)
  79.   DEF ret = FALSE
  80.   DEF hunk0offs, hunk0len
  81.   DEF r, tag:PTR TO rt, start:PTR TO LONG
  82.   DEF init = 0, i, x
  83.  
  84.   IF ((len < 40960) OR ((len AND 3) <> 0)) THEN RETURN FALSE
  85.  
  86.   -> check header
  87.   IF ((buf[] <> HUNK_HEADER) OR (buf[1] <> 0)) THEN RETURN FALSE
  88.   IF ((r := buf[2]) = 0) THEN RETURN FALSE
  89.   IF ((buf[4] - buf[3] + 1) <> r) THEN RETURN FALSE
  90.  
  91.   start := buf + 20
  92.   REPEAT
  93.     IF ((start[] AND $E0000000) = $C0000000)
  94.       ADDQ.L  #8,start
  95.     ELSE
  96.       ADDQ.L  #4,start
  97.     ENDIF
  98.     r--
  99.   UNTIL r = 0
  100.  
  101.   r := start[] AND $1FFFFFFF
  102.   IF ((r <> HUNK_CODE) AND (r <> HUNK_DATA)) THEN RETURN FALSE
  103.   hunk0len := start[1] * 4
  104.   hunk0offs := start + 8 - buf
  105.  
  106.   ->PrintF('hunk0offs: $\h[08] hunk0len: $\h[08]\n', hunk0offs, hunk0len)
  107.  
  108.   -> find ROMTag
  109.  
  110.   FOR r := 0 TO hunk0len STEP 2
  111.     EXIT ret
  112.     tag := buf + hunk0offs + r
  113.  
  114.     IF ((tag.matchword = RTC_MATCHWORD) AND
  115.       (tag.matchtag = r) AND
  116.       ((tag.endskip AND $FFF00000) = 0) AND
  117.       ((tag.flags AND Not(RTF_COLDSTART OR RTF_AFTERDOS OR RTF_AUTOINIT)) = 0) AND
  118.       (tag.type = NT_LIBRARY) AND
  119.       ((tag.name AND $FFF00000) = 0) AND
  120.       ((tag.idstring AND $FFF00000) = 0))
  121.  
  122.       ->PrintF('romtag at offset $\h\n', hunk0offs + r)
  123.  
  124.       -> find initcode
  125.       IF (tag.init)
  126.         init := hunk0offs + tag.init
  127.         IF (tag.flags AND RTF_AUTOINIT)
  128.           init := hunk0offs + Long(buf + init + 12)
  129.         ENDIF
  130.       ENDIF
  131.  
  132.       IF ((init > hunk0offs) AND (init < (hunk0offs + hunk0len - 2)))
  133.  
  134.         ->PrintF('initcode: $\h[08]\n', init)
  135.  
  136.         -> scan the init code for 'move.l a0,dn'
  137.         FOR i := 0 TO 32 STEP 2
  138.           x := Int(buf + init + i)
  139.           EXIT ((ret <> 0) OR (x = $4E75))
  140.           IF ((x AND $F1FF)  = $2008)
  141.             -> patch it! (moveq #0,dn)
  142.             PutInt(buf + init + i, (x AND $0E00) OR $7000)
  143.             ret := 1
  144.           ENDIF
  145.         ENDFOR
  146.       ENDIF
  147.     ENDIF
  148.   ENDFOR
  149. ENDPROC ret
  150.